﻿/*
 * Copyright (C) 2009-2010 Valerio Fuoglio <valerio.fuoglio@gmail.com>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Lastfm;
using Lastfm.Scrobbling;
using Lastfm.Services;

namespace LightScrobbler
{
    internal  partial class MainDialog
    {
        private Thread _thread;

        public void ReadLog()
        {
            _statusBarTextBox.BeginInvoke(new UpdateTextCallback(UpdateStatusText), new object[] { "Reading log " });
            var reader = new StreamReader(ScrobbleSessionData.GetInstance().FilePath, true);
            var played = new List<Entry>();
            var skipped = new List<Entry>();

            try
            {
                // Check the Log protocol version
                if (reader.ReadLine() != "#AUDIOSCROBBLER/1.1")
                    throw new Exception("Unsupported Logscrobbler protocol. Please update your application.");

                // Get timezone
                DateTimeKind kind;
                string timezoneLine = reader.ReadLine();
                if (timezoneLine == "#TZ/UTC")
                    kind = DateTimeKind.Utc;
                else
                    kind = DateTimeKind.Local;

                // Read the tracks
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();
                    if (line[0] == '#') continue;

                    // Worst case scenario, all vlaues are missing and the whole line is empty
                    var values = new List<string>(line.Split('\t'));

                    ScrobbleMode mode = ScrobbleMode.Played;
                    if (values[5] == "L")
                        mode = ScrobbleMode.Played;
                    else if (values[5] == "S")
                        mode = ScrobbleMode.Skipped;

                    /*
                     public Entry(string artist, string title, 
                     DateTime timeStarted, PlaybackSource source, 
                     TimeSpan duration, ScrobbleMode mode, string album, int trackNumber, string mbid)
                     */

                    string artist = values[0];
                    string title = values[2];
                    DateTime timeStarted = Utilities.TimestampToDateTime(long.Parse(values[6]), kind);
                    PlaybackSource source = PlaybackSource.User;
                    var duration = new TimeSpan(0, 0, int.Parse(values[4]));
                    string album = values[1];
                    int number = 0;
                    try
                    {
                        number = Int32.Parse(values[3]);
                    }
                    catch
                    {
                    }
                    // MBID not available in audioscrobbler 1.1
                    string mbid = "";

                    var track = new Entry(artist, title, timeStarted, source, duration, mode, album, number, mbid);

                    if (track.Mode == ScrobbleMode.Played)
                        played.Add(track);
                    else if (track.Mode == ScrobbleMode.Skipped)
                        skipped.Add(track);
                }
            }
            catch (Exception)
            {
                _statusBarTextBox.BeginInvoke(new UpdateTextCallback(UpdateStatusText), new object[] { "" });
                BeginInvoke(new ExitingThreadCallback(Read_Failed), null);
                return;
            }

            _playedTracks = played;
            _skippedTracks = skipped;
            _statusBarTextBox.BeginInvoke(new UpdateTextCallback(UpdateStatusText), new object[] { "" });
            BeginInvoke(new ExitingThreadCallback(Read_Post), null);
        }

        private void Read_Post()
        {
            
            if (_playedTracks.Count == 0)
            {
                if (_skippedTracks.Count == 0)
                    MessageBox.Show("Provided log doesn't contain any track to scrobble.", "Nothing to scrobble",
                                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                else
                {
                    var som = new SkippedOnlyMsg(_skippedTracks);
                    som.ShowDialog(this);
                }
            }
            else
            {
                ScrobbleSessionData ssd = ScrobbleSessionData.GetInstance();

                ssd.PlayedTracks = _playedTracks;
                ssd.SkippedTracks = _skippedTracks;

                // Manage options
                Dictionary<LightScrobblerOptions, object> options = ScrobbleSessionData.GetInstance().Options;

                options.Add(LightScrobblerOptions.DeleteLogFile, _deleteLogFileCheckbox.Checked);

                ssd.Options = options;
                ssd.SuccessifullySent = false;
                ssd.DriveLocked = true;

                Session session = ssd.Session;

                if (ssd.SessionState == SessionState.AuthenticationFailed)
                {
                    MessageBox.Show("Wrong username or password.",
                                    "Authentication failed", MessageBoxButtons.OK, MessageBoxIcon.Error,
                                    MessageBoxDefaultButton.Button1);
                    ssd.SuccessifullySent = false;
                }

                var fs = new FileSummary();
                fs.ShowDialog(this);

                ScrobbleSessionData.GetInstance().DriveLocked = false;
            }
            _readLogButton.Enabled = true;
            EnableControls(true);

            if (ScrobbleSessionData.GetInstance().SuccessifullySent)
                _selectFileTextBox.Text = "";

            return;
        }

        private void Read_Failed()
        {
            MessageBox.Show("Selected log file isn't a valid AudioScrobbler log or may be corruped",
                            "Error reading log file",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }

        #region Nested type: AbortThreadCallback

        internal delegate void AbortThreadCallback();

        #endregion

        #region Nested type: ExitingThreadCallback

        internal delegate void ExitingThreadCallback();

        #endregion
    }

}